package com.selfdiscipline.data.repository

import com.selfdiscipline.data.local.dao.HabitDao
import com.selfdiscipline.data.local.entity.HabitEntity
import com.selfdiscipline.domain.repository.HabitRepository
import kotlinx.coroutines.flow.Flow
import java.time.LocalDate
import java.time.LocalDateTime
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.first
import javax.inject.Inject

class HabitRepositoryImpl @Inject constructor(
    private val habitDao: HabitDao
) : HabitRepository {
    
    override fun getAllHabits(): Flow<List<HabitEntity>> {
        return habitDao.getAllHabits()
    }
    
    override fun getActiveHabits(): Flow<List<HabitEntity>> {
        return habitDao.getActiveHabits()
    }
    
    override suspend fun getHabitById(habitId: Long): HabitEntity? {
        return habitDao.getHabitById(habitId)
    }
    
    override suspend fun insertHabit(habit: HabitEntity): Long {
        return habitDao.insertHabit(habit)
    }
    
    override suspend fun updateHabit(habit: HabitEntity) {
        habitDao.updateHabit(habit)
    }
    
    override suspend fun deleteHabitById(habitId: Long) {
        habitDao.deleteHabitById(habitId)
    }
    
    override suspend fun completeHabit(id: Long, completedDate: LocalDate) {
        val habit = habitDao.getHabitById(id) ?: return
        
        // Calculate streak
        val previousCompletedDate = habit.lastCompletedDate
        val newStreak = if (previousCompletedDate != null && 
                             previousCompletedDate.plusDays(1) == completedDate) {
            // Consecutive day completion
            (habit.streak ?: 0) + 1
        } else {
            // Start a new streak
            1
        }
        
        // Calculate completion rate
        val newCompletionCount = habit.completionCount + 1
        val daysSinceCreation = habit.createdAt?.let {
            val creationDate = it.toLocalDate()
            java.time.temporal.ChronoUnit.DAYS.between(creationDate, completedDate) + 1
        } ?: 1
        val completionRate = newCompletionCount.toFloat() / daysSinceCreation.toFloat()
        
        // Update habit
        val updatedHabit = habit.copy(
            lastCompletedDate = completedDate,
            streak = newStreak,
            completionCount = newCompletionCount,
            completionRate = completionRate,
            updatedAt = LocalDateTime.now()
        )
        
        habitDao.updateHabit(updatedHabit)
    }
    
    override suspend fun getMaxStreak(): Int? {
        // Since this method is not implemented in the DAO, use a simple approach
        // by fetching all habits and finding the max streak
        val habits = habitDao.getAllHabits().first()
        return habits.maxOfOrNull { it.streak ?: 0 }
    }
    
    override fun getHabitsCompletedOnDate(date: LocalDate): Flow<List<HabitEntity>> {
        // Since there's no direct DAO method, filter the results in the repository
        return habitDao.getAllHabits().map { habits ->
            habits.filter { it.lastCompletedDate == date }
        }
    }
    
    override fun getCompletedHabitsInRange(startDate: LocalDateTime, endDate: LocalDateTime): Flow<List<HabitEntity>> {
        // Since there's no direct DAO method, filter the results in the repository
        return habitDao.getAllHabits().map { habits ->
            habits.filter { habit ->
                habit.lastCompletedDate?.let { completedDate ->
                    val completedDateTime = completedDate.atStartOfDay()
                    completedDateTime >= startDate && completedDateTime <= endDate
                } ?: false
            }
        }
    }
} 